#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <memory>
#include "thread.hpp"
#include "Mutex.hpp"


using namespace std;

//共享资源  ->火车票
int tickets = 100;
class ThreadData
{
public:
    ThreadData(const string& name,pthread_mutex_t* mutex_p)
    :_name(name),_mutex_p(mutex_p)
    {}
    ~ThreadData()
    {}
public:
    string _name;
    pthread_mutex_t* _mutex_p;
};
void* Get_tickets(void* args)
{
    ThreadData* td = static_cast<ThreadData*>(args);
    while(true)
    {
        //加锁和解锁的过程是多个线程串行执行的，所以程序变慢了
        //锁只规定互斥访问，没有规定谁先执行，也没有说必须一个一个执行

        pthread_mutex_lock(td->_mutex_p);   //加锁
        {
            // lockGroud mtx(td->_mutex_p);    //封装的锁  RAII风格
            if(tickets > 0)
            {   //微秒时间，1秒 = 1000毫秒 1毫秒 = 1000微秒...
                usleep(1245); //模拟抢票时间

                cout << td->_name << "正在抢票中... 票号："<< tickets-- << endl;   
                pthread_mutex_unlock(td->_mutex_p);  //解锁
            }
            else
            {   //不能直接在外面解锁，因为有break，会直接跳过，导致锁没有解开的场景
                pthread_mutex_unlock(td->_mutex_p);  
                break;
            }
        }
        usleep(1000);   //模拟形成订单页面给用户
    }
    return nullptr;
}

// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;   //静态分配
// void* Get_tickets(void* args)
// {
//     string username = static_cast<const char*>(args);
//     while(true)
//     {
//         pthread_mutex_lock(&lock);  //加锁
//         if(tickets > 0)
//         {   //微秒时间，1秒 = 1000毫秒 1毫秒 = 1000微秒...
//             usleep(1245); //模拟抢票时间

//             cout << username << "正在抢票中... 票号："<< tickets-- << endl;   
//             pthread_mutex_unlock(&lock);    //解锁
//         }
//         else
//         {//不能直接在外面解锁，因为有break，会直接跳过，导致锁没有解开的场景
//             pthread_mutex_unlock(&lock);    
//             break;
//         }
//         usleep(1000);   //模拟形成订单页面给用户
//     }
//     return nullptr;
// }
// int main()
// {
// #define NUM 4  
//         pthread_t t1,t2,t3,t4;
//         pthread_create(&t1,nullptr,Get_tickets,(void*)"thread 1");
//         pthread_create(&t2,nullptr,Get_tickets,(void*)"thread 2");
//         pthread_create(&t3,nullptr,Get_tickets,(void*)"thread 3");
//         pthread_create(&t4,nullptr,Get_tickets,(void*)"thread 4");

//         pthread_join(t1,nullptr);
//         pthread_join(t2,nullptr);
//         pthread_join(t3,nullptr);
//         pthread_join(t4,nullptr);
//     return 0;
// }

int main()
{
#define NUM 4
    pthread_mutex_t lock;
    pthread_mutex_init(&lock,nullptr);  //初始化锁

    vector<pthread_t> tids(NUM);

    for(int i = 0;i<NUM;++i)
    {
        char buffer[64];
        snprintf(buffer,sizeof(buffer),"thread %d",i+1);
        ThreadData* td = new ThreadData(buffer,&lock);
        pthread_create(&tids[i],nullptr,Get_tickets,td);
    }
    for(const auto& Tids:tids)
    {
        pthread_join(Tids,nullptr);
    }

    pthread_mutex_destroy(&lock);//销毁锁
    return 0;
}



// int main()
// {
//     unique_ptr<Thread> thread1(new Thread(Get_tickets,(void*)"user1 ",1));
//     unique_ptr<Thread> thread2(new Thread(Get_tickets,(void*)"user2 ",2));
//     unique_ptr<Thread> thread3(new Thread(Get_tickets,(void*)"user3 ",3));
//     unique_ptr<Thread> thread4(new Thread(Get_tickets,(void*)"user4 ",4));

//     thread1->join();
//     thread2->join();
//     thread3->join();
//     thread4->join();

//     return 0;
// }